if not pcall(require,'maximaeval.capture') then
    error('Fail: were some errors loading capture.lua')
end

local function call_maxima (expression)
    local output =  assert(os.capture(string.format(
            'maxima -q --batch-string="%s;"',expression),true))

    local filtered = output.match(output,
    '%(%%i%d+%)(.*)$')

    return filtered
end

local function evaluate_line (cursor_pos)
    local line = vim.api.nvim_buf_get_lines(0, cursor_pos-1, cursor_pos, false)[1]
    local expression_iter = string.gmatch(line,'%$%$ *([%-%w%(%)%%][%w%(%)%%%.%,%;%:%"%\'%s%^%*%+%-]+[%(%)%w%p]) *%$%$')

    local expression_count = 1
    local res_table = {}
    for expression in expression_iter do
        local res = call_maxima(expression)
        table.insert(res_table, string.format('[maxima %d]',expression_count))
        expression_count = expression_count+1

        res = string.gsub(string.gsub(res,'%(%%o%d+%)',
            string.rep(' ',string.len(string.match(res,'%(%%o%d+%)')),'')),'\n',';;')

        local matcher = string.gmatch(res,'([%s%w%d%(%)%^%-%=%+%.%/%|%<%>]+);;')
        matcher() -- Removing the first iteration (the remainder of the input expression).
        for r in matcher do
            table.insert(res_table,r)
        end

        table.insert(res_table,'------')
    end
    vim.api.nvim_buf_set_lines(0,cursor_pos,cursor_pos,false,res_table)
    return #res_table
end

-- Takes maxima command from the buffer attached to the cursor position and gets all the $$ ... $$ 
-- expressions to evaluate them in maxima.
-- Returns the procedural expression result directly from maxima but filtering indexing and repeated
-- expressions.
vim.api.nvim_create_user_command('MaximaEval', function()
    local cursor_pos = vim.api.nvim_win_get_cursor(0)[1]
    evaluate_line(cursor_pos)
end,{})


vim.api.nvim_create_user_command ('MaximaEvalBuffer', function()
    local lines = vim.api.nvim_buf_line_count(0)

    local line_counter = 1
    for _ = 1,lines do
        line_counter = 1 + line_counter + evaluate_line(line_counter)
    end
end,{})

